/*
 * Created by Wildish on 2016-10-31
 *
 * Contact me with keithknight@qq.com
 *
 * Copyright (c) 2016 Wildish
 */

package com.wildish.hybridframework.utils.sign;

import org.apache.commons.lang3.StringUtils;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EncryptUtil {
    private static final String kk = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=";

    public static final String encode(HashMap<String, String> params, int key) {
        StringBuffer sb = new StringBuffer();
        for(Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator(); iterator.hasNext();) {
            Map.Entry<String, String> entry = iterator.next();
            try{
                sb.append(entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
            } catch (Exception e) {

            }
            sb.append("&");
        }
        return encode(sb.toString().substring(0, sb.toString().length() - 1), key);
    }

    public static final String encode(String s, int k) {
        if(StringUtils.isBlank(s)) {
            return "";
        }
        ArrayList<Character> r = new ArrayList<>();
        int idx = 0, c1, c2, c3, kc;
        while (idx + 2 < s.length()) {
            c1 = 0x00FF & s.charAt(idx++);
            c2 = 0x00FF & s.charAt(idx++);
            c3 = 0x00FF & s.charAt(idx++);
            kc = (c1 << 16) + (c2 << 8) + c3 + k;
            r.add(kk.charAt(kc & 0x3F));
            r.add(kk.charAt((kc >> 6) & 0x3F));
            r.add(kk.charAt((kc >> 12) & 0x3F));
            r.add(kk.charAt((kc >> 18) & 0x3F));
        }
        if (idx + 1 == s.length()) {
            kc = (s.charAt(idx) << 16) + k;
            r.add(kk.charAt(kc & 0x3F));
            r.add(kk.charAt((kc >> 6) & 0x3F));
            r.add(kk.charAt((kc >> 12) & 0x3F));
            r.add(kk.charAt((kc >> 18) & 0x3F));
        } else if (idx + 2 == s.length()) {
            kc = (s.charAt(idx) << 16) + (s.charAt(idx + 1) << 8) + k;
            r.add(kk.charAt(kc & 0x3F));
            r.add(kk.charAt((kc >> 6) & 0x3F));
            r.add(kk.charAt((kc >> 12) & 0x3F));
            r.add(kk.charAt((kc >> 18) & 0x3F));
        }
        String result = "";
        for(int i = 0; i != r.size(); i++) {
            result += r.get(i);
        }
        return result;
    }

	private static int index(char ch) {
		if (ch == '=') {
			return 63;
		} else if (ch == '-') {
			return 62;
		} else if (ch <= '9' && ch >= '0') {
			return ch - '0' + 52;
		} else if (ch <= 'Z' && ch >= 'A') {
			return ch - 'A' + 26;
		} else if (ch <= 'z' && ch >= 'a') {
			return ch - 'a';
		} else {
			return 0;
		}
	}

	private static String decode(String msg, int key) {
		int idx = 0;
		StringBuffer sb = new StringBuffer();
		int len = msg.length();
		if (len % 4 != 0) {
			return msg;
		}
		//
		while (idx < len) {
			int n1 = index(msg.charAt(idx++));
			int n2 = index(msg.charAt(idx++));
			int n3 = index(msg.charAt(idx++));
			int n4 = index(msg.charAt(idx++));
			int n = n1 + (n2 << 6) + (n3 << 12) + (n4 << 18) - key;
			int c1 = (n >> 16) & 0x000000FF;
			int c2 = (n >> 8) & 0x000000FF;
			int c3 = n & 0x000000FF;
			if (c1 != 0) {
				sb.append((char) c1);
			}

			if (c2 != 0) {
				sb.append((char) c2);
			}

			if (c3 != 0) {
				sb.append((char) c3);
			}
		}
		return sb.toString();
	}

	private static Pattern urlParamPattern = Pattern.compile("[&?]?([^=]+)=([^&]*)");
	public static HashMap<String, String> decodeParams(String content, int key) throws Exception {
		HashMap<String, String> result = new HashMap<>();
		
		String str = decode(content, key);
		Matcher m = urlParamPattern.matcher(str);
		while (m.find()) {
			result.put("?" + m.group(1), URLDecoder.decode(m.group(2), "UTF-8"));
		}
		return result;
	}
}
